2

前言

前端开发中总是要和接口和缓存打交道,所以HTTP相关内容多多少少还是要知道一些,干起活来才能事半功倍。下面我从业务出发,简单说下一些可能会碰到的知识点。
为了尽可能减少自己表述上的不严谨,文中会有不少外链,建议大家还是能点进去看一下,也欢迎帮忙纠正。

开始前的准备

老司机可以直接忽略本段内容,我们先简单了解下 HTTP 的基本知识

什么是HTTP协议

HTTPHypertext Transfer Protocol 超文本传输协议 的缩写,和 HTML 一样都是出自Hypertext家族的。处于OSI model中的应用层。
目前为止,经历了几个版本的迭代到了2, HTTP/3目前也是即将要标准化了
关于目前所有的HTTP相关协议的目录可以直接看这里

wikipedia上关于HTTP的介绍

The Hypertext Transfer Protocol (HTTP) is an application protocol for distributed, collaborative, hypermedia information systems.1 HTTP is the foundation of data communication for the World Wide Web, where hypertext documents include hyperlinks to other resources that the user can easily access, for example by a mouse click or by tapping the screen in a web browser. HTTP was developed to facilitate hypertext and the World Wide Web.

Development of HTTP was initiated by Tim Berners-Lee at CERN in 1989. Development of HTTP standards was coordinated by the Internet Engineering Task Force (IETF) and the World Wide Web Consortium (W3C), culminating in the publication of a series of Requests for Comments (RFCs). The first definition of HTTP/1.1, the version of HTTP in common use, occurred in RFC 2068 in 1997, although this was made obsolete by RFC 2616 in 1999 and then again by the RFC 7230 family of RFCs in 2014.

A later version, the successor HTTP/2, was standardized in 2015 (and HTTP/3 is its proposed successor (Internet Draft), that builds on HTTP/22), and is now supported by major web servers and browsers over Transport Layer Security (TLS) using Application-Layer Protocol Negotiation (ALPN) extension4 where TLS 1.2 or newer is required.5

起始

最早是由万维网的创始人Tim Berners-Lee 在1989年发起并于1990年完成了第一次服务器与客户端之间的通讯。

HTTP/0.9

发布于1991年的0.9版本,当时只有一个GET命令,只能回应HTML格式的字符串,结束以后就关闭TCP连接

HTTP/1.0 RFC-1945

发布于1996年的 1.0 版本,除了最早的 GET 以外还引入了POSTHEAD 命令,以及各类标识缓存,请求状态等headers,使任何文件都可以通过http请求进行传输。

HTTP/1.1 RFC-2616 (已废弃)

发布于1999年的 1.1 版本,也是目前使用基数最大的版本,
新增了几个基础 Method

  • PUT
  • DELETE
  • TRACE
  • OPTIONS
  • CONNECT

弥补了之前HTTP/1.0的一些不足, 包括:

  • 完善了之前缓存相关的设定,也便有了我们现在常说的强缓存协商缓存的概念
  • 默认采用持久连接,并能很好地配合代理服务器工作。支持以piplining的方式同时发送多个请求,从而降低了线路的负载也提升了HTTP请求的响应速度。
  • 部分安全性问题

HTTP/1.1 RFC-7230 (新)

新版的HTTP1.1被拆分成了了以下几个模块

HTTP/2.0 RFC-7540

发布于2015年的 2.0 版本,也是当前的最新标准。

基于谷歌提出的SPDY而来,之前用于Chrome浏览器中来访问Google的SSL加密服务,在HTTP/2发布后功成身退。

主要新增了以下内容

  • 多路复用
  • 请求头压缩 HPACK: RFC-7541
  • 帧、消息、流和TCP连接
  • 服务器推送

因为强制绑定了TLS,相关的证书又是一笔新的开支,加上各种历史遗留问题,目前大部分公司对HTTP/2的支持也是较为尴尬,就如同 ES6 一般,在落地好多年后依旧会被叫做新特性
而解决的问题如服务器推送之类的在之前是可以通过websocket甚至客户端轮询等操作解决,而头部压缩等也只是对现有方式进行了少部分优化,所以实际应用也没那么多,而出现的不确定性又增多了,而本身又揽了一些TCP干的活,所以协议定下后争议还是挺多的。

可能还需要时间把老服务器老电脑老项目老程序员给替换掉才行。

1. 缓存 RFC-7234

顾名思义,缓存就是浏览器存储数据的地方,平时你可以通过特定的浏览器功能存储一些数据,比如localStorage ,sessionStorage,但这些都是用户通过脚本主动向浏览器添加的东西。
但是还有一些是我们希望加快用户效率而存下的数据,但很多时候用户总是特别喜欢用各类管家清理的东西,那就是HTTP的缓存了。

而缓存的作用是方便浏览器更快地读取数据而不用反复和服务器确认。前端对于缓存这件事,用得好,事半功倍,没用对,可能会让你踏入无底深渊。

那我们首先了解下几个常见的缓存相关的请求头和响应头:

  • Expires: 缓存的过期时间
  • Age: 文件的寿命
  • Cache-Control / Pragma : 在HTTP/1 的年代用Pragma,因为那个时候还没Cache-Control, 如果你在请求中看到这个头,那多半是为了做兼容

    • s-max-age
    • max-age
    • private
    • public
    • no-cache
    • no-store
    • must-revalidate
  • Warning 主要是以几个可能会出现的异常信息的返回码,参考[iana]
  • ETag 与 If-None-Match
  • Last-Modified 与If-Modified-Since (HTTP:1.0 ):

关于强制缓存还是协商缓存...

不知道是不是我没翻对地方,还是这本来就是国内大家都在来回翻二手资料翻出来的乌龙,翻了一整个RFC-7234也没翻到和这俩词汇表达相关的内容,如果有相关文献麻烦告知一二。
不过在我自己的理解上
网上所说的协商缓存大致就是该不该返回304,避免再拉一遍文件。
而强缓存就是是不是返回200(from disk)的概念
而通过Cache-Control来区别不缓存所有接口只返回200呢还是只做了基本时间校验的缓存 200(from disk) ,200(from memory)还是需要通过请求头以及返回头来确认文件是否更改的 304(Not Modified)

现在:问题来了

这几年前端体系越来越健全,spa也开始大行其道,一名初出茅庐的前端新人也能基于开源项目快速构建出一个单页应用。
那么你是否碰到过新版本项目打包了上线了,结果一进去却是缓存,还需要刷新一下才行,有时候刷新可能都不一定有用?
而更新本来就是悄咪咪进行的,用户如果打不开页面就换个服务了,根本不会给你第二次机会。
所以我们肯定要把这个文件的缓存去掉,但除了html文件不缓存以外,其他的jscss文件我又要做缓存而且越久越好,但业务要更新的时候我可能又要把老的文件的缓存去掉,那该怎么办?

CDN

先简单说下CDN是个什么东西,我们的代码就像一个放在服务器的包裹,而用户从我们的服务器中取包裹就像网购一般,要先判断能不能拿到,比如

  • 地方太远,运费太贵[网络超时]
  • 比如地址填错快递无法送达[404]
  • 打包的下班了,服务器重启服务[500]
  • 快递太多服务器吃不消

而普通的用服务器发版就是很早以前淘宝小商户的模式,你要准备仓库又准备很多钱提前租仓库囤货找员工,但是你又不知道会有多少客户来买东西,万一客户少了就赔本,万一客户多了又忙不过来爆仓或者货准备太少不够发,而且很多海外的客户快递也没办法发。
而CDN就像一个分布于全国的物流仓储点,你把代码告诉一台主服务器,然后这个服务器就会把这份数据复制很多份发到分部于全国各地的代理数据仓库。
然后对应地区的客户去找对应的代理服务器拿货,这样速度也快,存货也足,价格也便宜。
但是随之而来的问题就是发出去的货容易,收回来难,嗯,我把代码发出去就没准备收回来。
所以发出去的代码我们需要在后面加上对应的hash指纹
这就是为什么很多webpack配置脚手架打包的文件都带个hash
至于找到它们的事情就交给index.html

NGINX

生成的html文件我们有了几个新去处,可以发到公司服务器里的nginx再加上一行不缓存的header

location ~ .*\.(htm|html )$ {
    add_header Cache-Control no-store;
}

然后可以通过替换html文件做一个简单的脱离后端服务的无感知更新
甚至可以配合后端实现蓝绿部署

【待续】


MaxChan
462 声望29 粉丝

就叫我陈英俊吧